package com.googlecode.elidom.common.metadata;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import net.sf.common.util.BeanUtils;
import net.sf.common.util.Closure;
import net.sf.common.util.SyncCtrlUtils;
import net.sf.common.util.ValueUtils;

import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.annotate.JsonIgnore;

public class Service {
	private String name;
	private String description;
	@JsonIgnore
	private Object bean;
	@JsonIgnore
	private Method method;
	private Class<?> inputType;
	private Class<?> outputType;
	private List<DataType> types;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public Object getBean() {
		return bean;
	}
	public void setBean(Object bean) {
		this.bean = bean;
	}
	public Method getMethod() {
		return method;
	}
	public void setMethod(Method method) {
		this.method = method;
	}
	public Class<?> getInputType() {
		return inputType;
	}
	public void setInputType(Class<?> inputType) {
		this.inputType = inputType;
	}
	public Class<?> getOutputType() {
		return outputType;
	}
	public void setOutputType(Class<?> outputType) {
		this.outputType = outputType;
	}
	public List<DataType> getTypes() {
		return types;
	}
	public void setTypes(List<DataType> types) {
		this.types = types;
	}

	public static class DataType {
		private String name;
		private Map<String, ?> constants;
		private List<DataField> fields;
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public Map<String, ?> getConstants() {
			return constants;
		}
		public void setConstants(Map<String, ?> constants) {
			this.constants = constants;
		}
		public List<DataField> getFields() {
			return fields;
		}
		public void setFields(List<DataField> fields) {
			this.fields = fields;
		}
	}

	public static class DataField {
		private String name;
		private String type;
		private Object value;
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getType() {
			return type;
		}
		public void setType(String type) {
			this.type = type;
		}
		public Object getValue() {
			return value;
		}
		public void setValue(Object value) {
			this.value = value;
		}
	}

	private static final Map<String, Service> CACHE = new ConcurrentHashMap<String, Service>();
	public static Service get(final String name) throws Exception {
		if (CACHE.containsKey(name))
			return CACHE.get(name);
		return SyncCtrlUtils.wrap("service." + name, CACHE, name, new Closure<Service, Exception>() {
			@Override
			public Service execute() throws Exception {
				int index = name.indexOf('-');
				if (index <= 0)
					throw new IllegalArgumentException("Service name must have '-' character: " + name);
				String cat = name.substring(0, index);
				String mName = name.substring(index + 1);
				String pName = StringUtils.replace(mName, "-", "_");
				String cName = ValueUtils.toCamelCase(mName, '-', true);
				String className = "com.googlecode.elidom." + cat + ".service." + pName + "." + cName;
				Class<?> clazz = ClassUtils.getClass(className);
				BeanUtils.getInstance("elidom");
				Service service = new Service();
				return service;
			}
		});
	}
}
